﻿using System;
using System.Drawing;
using Petra.Gis.Geometry.Support;

namespace Petra.Gis.RenderingServices.PlanarBase 
{
  /// <summary>
  /// DisplayTransformMatrix is map display transformation Matrix
  /// world coordinate is transformed by given offset, scale and rotation
  /// to display map local coordinates
  /// this class supports transformation of <c>PointD</c> and can return <c>System.Drawing.Point</c>[]
  /// </summary>
  public class DisplayTransformMatrix
  {
    //private System.Drawing.Drawing2D.DisplayTransformMatrix _matrix ;

    protected double[] _matrixArray = new double[9];


    #region construcors

    public DisplayTransformMatrix()
    {
      _matrixArray[0] = 1;
      _matrixArray[1] = 0;
      _matrixArray[2] = 0;

      _matrixArray[3] = 0;
      _matrixArray[4] = 1;
      _matrixArray[5] = 0;

      _matrixArray[6] = 0;
      _matrixArray[7] = 0;
      _matrixArray[8] = 1;
    }



    public DisplayTransformMatrix(float m11, float m12, float m21, float m22, float dx, float dy) : this()
    {
      _matrixArray[0] = m11;
      _matrixArray[1] = m12;
      
      _matrixArray[3] = m21;
      _matrixArray[4] = m22;

      _matrixArray[6] = dx;
      _matrixArray[7] = dy;
    }


    #endregion construcors


    #region public props


    public double OffsetX
    {
      get { return _matrixArray[6]; }
      set { _matrixArray[6] = value; }
    }




    public double OffsetY
    {
      get { return _matrixArray[7]; }
      set { _matrixArray[7] = value; }
    }




    public double ScaleX
    {
      get { return _matrixArray[0]; }
      set { _matrixArray[0] = value; }
    }




    public double ScaleY
    {
      get { return _matrixArray[4]; }
      set { _matrixArray[4] = value; }
    }




    public double Rotation
    {
      get { return 0.0; }
      //set { _matrixArray[4] = value; }
    }




    /// <summary>
    /// Applies the specified translation vector (offsetX and offsetY) to this DisplayTransformMatrix by prepending the translation vector.
    /// </summary>
    /// <param name="offsetX">The horizontal value by which to translate this DisplayTransformMatrix.</param>
    /// <param name="offsetY">The vertical value by which to translate this DisplayTransformMatrix.</param>
    public void Translate(double offsetX, double offsetY)
    {
      _matrixArray[6] = offsetX;
      _matrixArray[7] = offsetY;
    }



    /// <summary>
    /// Applies the specified scale vector to this DisplayTransformMatrix by prepending the scale vector.
    /// </summary>
    /// <param name="scaleX">The value by which to scale this DisplayTransformMatrix in the horizontal direction</param>
    /// <param name="scaleY">The value by which to scale this DisplayTransformMatrix in the vertical direction</param>
    public void Scale(float scaleX, float scaleY)
    {
      _matrixArray[0] = scaleX;
      _matrixArray[4] = scaleY;
    }



    public void Scale(double scaleX, double scaleY)
    {
      _matrixArray[0] = scaleX;
      _matrixArray[4] = scaleY;
    }




    /// <summary>
    /// Prepend to this DisplayTransformMatrix a clockwise rotation, around the origin and by the specified angle.
    /// </summary>
    /// <param name="angle">The angle of the rotation, in degrees.</param>
    public void Rotate(float angle)
    {
      //not implemented 
    }



    public int TransformScalarX(double scalarValue)
    {
      //can use X

      scalarValue *= _matrixArray[4];

      return (int)scalarValue;

    }


    #endregion public props



    public Point TransformPoint(PointD inputPoint)
    {
      Point outPt = new Point();

      //translate
      inputPoint.X -= _matrixArray[6];
      inputPoint.Y -= _matrixArray[7];

      //scale
      inputPoint.X *= _matrixArray[0];
      inputPoint.Y *= _matrixArray[4];

      outPt.X = (int)inputPoint.X;
      outPt.Y = (int)inputPoint.Y;

      return outPt;
    }




    public Point transformPoint(PointF point)
    {

      PointD inputPoint = new PointD(point.X, point.Y);

      return TransformPoint(inputPoint);

    }




    public Point TransformPoint(Coordinate coord)
    {

      PointD inputPoint = new PointD(coord.X, coord.Y);

      return TransformPoint(inputPoint);
    }




    public Point TransformPoint(double horizontal, double vertical)
    {

      PointD inputPoint = new PointD(horizontal, vertical);

      return TransformPoint(inputPoint);
    }






  }
}
